
package com.haiyou.common.util.collect;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

import com.google.common.collect.Lists;

public class ArrayUtils {

	public static <E> boolean contains(E[] arr, E target) {

		for (int i = arr.length; --i >= 0;) {
			if (arr[i].equals(target)) {
				return true;
			}
		}
		return false;
	}

	public static boolean contains(int[] arr, int target) {

		for (int i = arr.length; --i >= 0;) {
			if (arr[i] == target) {
				return true;
			}
		}
		return false;
	}

	public static boolean equals(byte[] arr1, byte[] arr2) {

		return Arrays.equals(arr1, arr2);
	}

	public static boolean equals(short[] arr1, short[] arr2) {

		return Arrays.equals(arr1, arr2);
	}

	public static boolean equals(int[] arr1, int[] arr2) {

		return Arrays.equals(arr1, arr2);
	}

	public static boolean equals(long[] arr1, long[] arr2) {

		return Arrays.equals(arr1, arr2);
	}

	public static boolean equals(float[] arr1, float[] arr2) {

		return Arrays.equals(arr1, arr2);
	}

	public static boolean equals(double[] arr1, double[] arr2) {

		return Arrays.equals(arr1, arr2);
	}

	public static boolean equals(boolean[] arr1, boolean[] arr2) {

		return Arrays.equals(arr1, arr2);
	}

	public static boolean equals(char[] arr1, char[] arr2) {

		return Arrays.equals(arr1, arr2);
	}

	public static boolean equals(String[] arr1, String[] arr2) {

		return Arrays.equals(arr1, arr2);
	}

	public static boolean equals(Object[] arr1, Object[] arr2) {

		return Arrays.equals(arr1, arr2);
	}

	public static boolean deepEquals(Object[] arr1, Object[] arr2) {

		return Arrays.deepEquals(arr1, arr2);
	}

	public static int hashCode(Object[] arr) {

		return Arrays.hashCode(arr);
	}

	public static int deepHashCode(Object[] arr) {

		return Arrays.deepHashCode(arr);
	}

	public static <E> E[] subArray(E[] src, int begin, int end) {

		try {
			return Arrays.copyOfRange(src, begin, end);
		} catch (Exception e) {
			throw new RuntimeException(String.format("subArray from[%d]to[%d],size=[%d]", begin, end, src.length), e);
		}
	}

	final static public <E> List<E> toList(E... args) {

		return Lists.newArrayList((Arrays.asList(args)));
	}

	final static public <E> E[] toArray(Collection<E> c, Class<E> cls) {

		E[] arr = (E[]) Array.newInstance(cls, c.size());
		Iterator<E> iterator = c.iterator();
		int i = 0;
		while (iterator.hasNext()) {
			arr[i++] = iterator.next();
		}
		return arr;
	}

	/**
	 * 二分法倒转,效率更高
	 * 
	 * @param array
	 * @return
	 */
	public static byte[] reversed2(byte[] array) {
		int start = 0;
		int end = array.length - 1;
		int mid = array.length / 2;
		while (true) {
			if (start >= mid && end <= mid)
				break;
			byte s = array[start];
			byte e = array[end];
			array[end] = s;
			array[start] = e;
			start++;
			end--;
		}
		return array;
	}

	/**
	 * 二分法倒转,效率更高
	 * 
	 * @param array
	 * @return
	 */
	public static char[] reversed2(char[] chars) {
		int start = 0;
		int end = chars.length - 1;
		int mid = chars.length / 2;
		while (true) {
			if (start >= mid && end <= mid)
				break;
			char s = chars[start];
			char e = chars[end];
			chars[end] = s;
			chars[start] = e;
			start++;
			end--;
		}
		return chars;
	}

	/**
	 * 二分法倒转,效率更高
	 * 
	 * @param array
	 * @return
	 */
	public static <E> E[] reversed2(E[] array) {
		int start = 0;
		int end = array.length - 1;
		int mid = array.length / 2;
		while (true) {
			if (start >= mid && end <= mid)
				break;
			E s = array[start];
			E e = array[end];
			array[end] = s;
			array[start] = e;
			start++;
			end--;
		}
		return array;
	}

	/**
	 * 二分法倒转,效率更高
	 * 
	 * @param list
	 * @return
	 */
	public static <E> List<E> reversed2(List<E> list) {
		int start = 0;
		int end = list.size() - 1;
		int mid = list.size() / 2;
		while (true) {
			if (start >= mid && end <= mid)
				break;
			E s = list.get(start);
			E e = list.get(end);
			list.set(end, s);
			list.set(start, e);
			start++;
			end--;
		}
		return list;
	}

	/**
	 * 倒转
	 * 
	 * @return
	 */
	final static public <E> List<E> reversedList(List<E> list) {
		List<E> result = Lists.newArrayListWithCapacity(list.size());
		for (int i = list.size(); --i >= 0;) {
			result.add(list.get(i));
		}
		return result;
	}

	/**
	 * 倒转
	 * 
	 * @param c
	 * @return
	 */
	final static public <E> E[] reversedArray(E[] array, Class<E> cls) {
		E[] result = (E[]) Array.newInstance(cls, array.length);
		for (int i = array.length; --i >= 0;) {
			result[i] = array[array.length - 1 - i];
		}
		return result;
	}

	/**
	 * 倒转
	 * 
	 * @param array
	 * @return
	 */
	final static public byte[] reversedByteArray(byte[] array) {
		byte[] result = new byte[array.length];
		for (int i = array.length; --i >= 0;) {
			result[i] = array[array.length - 1 - i];
		}
		return result;
	}

	public static <E> E find2One(List<E> list, java.util.function.Predicate<E> predicate) {
		return list.stream().filter(e -> predicate.test(e)).findFirst().orElse(null);
	}

	public static <E> List<E> find2(List<E> list, java.util.function.Predicate<E> predicate) {
		return list.stream().filter(e -> predicate.test(e)).collect(Collectors.toList());
	}

	final static public int[] toArray(Integer[] arr) {
		int[] _arr = new int[arr.length];
		for (int i = 0; i < _arr.length; i++) {
			_arr[i] = arr[i];
		}
		return _arr;
	}

	final static public int[] toArray(List<Integer> list) {
		int[] _arr = new int[list.size()];
		for (int i = 0; i < _arr.length; i++) {
			_arr[i] = list.get(i);
		}
		return _arr;
	}

	final static public boolean isShun(List<Integer> list) {
		// Collections.sort(list);
		SortUtils.quickSort(list, 0, list.size() - 1);
		for (int i = 0; i < list.size() - 1; i++) {
			int now = list.get(i);
			int next = list.get(i + 1);
			if (next - now != 1) {
				return false;
			}
		}
		return true;
	}

	public static boolean isShun(int[] arr) {
		// Arrays.sort(arr);
		SortUtils.quickSort(arr, 0, arr.length - 1);
		for (int i = 0; i < arr.length - 1; i++) {
			int now = arr[i];
			int next = arr[i + 1];
			if (next - now != 1) {
				return false;
			}
		}
		return true;
	}

	public static <E> boolean isEmpty(E[] arr) {
		return arr == null || arr.length < 1;
	}

	/**
	 * 判断二维数组里面是否有元素
	 * 
	 * @param arr
	 * @return
	 */
	public static boolean isEmpty(int[][] arr) {
		if (arr == null || arr.length <= 0)
			return true;
		for (int[] es : arr) {
			if (es != null && es.length > 0)
				return false;
		}
		return true;
	}

	public static int[][] list2Arr(List<int[]> list) {
		if (CollectionUtils.isEmpty(list)) {
			return null;
		}
		int[][] arrs = new int[list.size()][];
		int size = list.size();
		for (int i = 0; i < size; i++) {
			int[] arr = list.get(i);
			arrs[i] = new int[arr.length];
			System.arraycopy(arr, 0, arrs[i], 0, arr.length);
		}
		return arrs;
	}

}
